/*
 * @Description  : the IFU module of the cpu
 * @authorName   : GuoJi
 * @github       : https://github.com/guoji-kk
 * @gitee        : https://gitee.com/guoji13663585559
 * @email        : 13663585559@163.com
 * @version      : 1.0
 * @Date         : 2023-05-14 23:34:46
 * @LastEditTime : 2023-05-16 20:18:15
 */

module ifu(nPC_sel,zero,clk,rst,instruction,j_sel,jValue);
	input clk,rst;
	input [1:0]nPC_sel;
	input [31:0]zero;  //zero=Alu_out
	input j_sel;
	input [25:0]jValue;
	output [31:0]instruction;
  
	reg [31:0]pc;
	reg [7:0]im[2047:0];    //2KB IM 2048*8bit
	reg [31:0]pcnew;
  	wire[31:0]temp,t0,t1;  //t1 t2 for adder in/out
 	wire[15:0]imm16;       //16 bit immediate number
  	reg [31:0]extout;      //extender output
  
  	//get instruction a value
	//the instruction deepth is 2048 ,just use 11 bit to discribe
  	assign instruction={im[pc[10:0]],im[pc[10:0]+1],im[pc[10:0]+2],im[pc[10:0]+3]}; 
										    
  	assign imm16 = instruction[15:0];
  
	assign jValue= instruction[25:0]; 
  	//set extout value
  	assign temp={{16{imm16[15]}},imm16}; //fuhaowei kuozhan
  
  
  	//j condition
  	always@(*)begin
    		if(j_sel==1)begin
      			extout={pc[31:28],jValue[25:0],2'b00}; 
   		end
      		if(j_sel==0)begin
      			extout=temp[31:0]<<2; //branch *4
   		end
  	end
    
	//set pcnew  two input of pc
  	assign t0=pc+4; 
  	assign t1=t0+extout; 
  	//set MUX
	always@(*)begin
    		if(nPC_sel==2'b00)begin  //+4
      			pcnew=t0;        //pc+4
    		end
    		else if(nPC_sel==2'b01)begin  //branch
      			pcnew=t1;  
    		end
    		else if(nPC_sel==2'b10)begin  //beq
      			if(zero==0)begin      ////zero=Alu_out
        			pcnew=t1; //branch
      			end
    			else begin
      				pcnew=t0;  //PC+4
   			end
    		end
    		else if(nPC_sel==2'b11)begin   //bne
      			if(zero==0)begin
        			pcnew=t0;  //PC+4
      			end
    			else begin
      				pcnew=t1;  //branch
   			end
    		end
  	end
  
  	//reset
  	always@(posedge clk or negedge rst)begin
    		if(!rst) 
			pc=32'h0000_3000; //pc initial value
      		else if(j_sel==0) 
			pc=pcnew;         //pc work , go to next instruction
      		else if(j_sel==1)
			pc=extout;	//jump to extout={pc[31:28],jValue[25:0],2'b00}; 
  	end
  
endmodule
    
